﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Linq;

namespace Gmantis.Controls.Chart
{
    internal interface ILayout
    {
        // Methods
        void UpdateLayout();
    }

    internal class ChartViewport2D : Canvas, ICoordConverter, ILayout
    {
        // Fields
        private AxisStyle _ast;
        internal Axis _ax;
        private AxisCanvasCollection _axes = new AxisCanvasCollection();
        internal Axis _ay;
        private Canvas _intCanvas = new Canvas();
        private Rect _plot = new Rect();
        private Rect _plot0 = new Rect();
        private RadarView _radarView = new RadarView();
        internal bool _rebuild = true;
        private int _startDataIdx = -1;
        private ChartView _view;

        // Methods
        internal ChartViewport2D(ChartView view)
        {
            base.Children.Add(this._intCanvas);
            this._view = view;
            this._ax = view.AxisX;
            this._ay = view.AxisY;
            this._axes.Add(this._ax);
            this._axes.Add(this._ay);
            this.InternalChildren.Add(this._ax);
            this.InternalChildren.Add(this._ay);
        }

        internal void AddAxis(Axis ax)
        {
            Axis item = ax;
            this._axes.Add(item);
            if (this._startDataIdx >= 0)
            {
                this.InternalChildren.Insert(this._startDataIdx++, item);
            }
            else
            {
                this.InternalChildren.Add(item);
            }
        }

        private void AdjustMargins(Size arrangeSize, ref double left, ref double right, ref double top, ref double bottom, ref double w, ref double h, ref double l0, ref double r0, ref double t0, ref double b0)
        {
            Thickness margin = this._view.Margin;
            l0 = left = (margin.Left != 0.0) ? margin.Left : Math.Max(left, l0);
            r0 = right = (margin.Right != 0.0) ? (arrangeSize.Width - margin.Right) : Math.Min(right, r0);
            t0 = top = (margin.Top != 0.0) ? margin.Top : Math.Max(top, t0);
            b0 = bottom = (margin.Bottom != 0.0) ? (arrangeSize.Height - margin.Bottom) : Math.Min(bottom, b0);
            w = right - left;
            h = bottom - top;
            if (w < 1.0)
            {
                w = 1.0;
            }
            if (h < 1.0)
            {
                h = 1.0;
            }
        }

        void ILayout.UpdateLayout()
        {
            if (this.CanUpdate())
            {
                this.UpdateLayout(new Size(base.ActualWidth, base.ActualHeight));
            }
        }

        private bool CanUpdate()
        {
            Chart chart = null;
            for (FrameworkElement element = base.Parent as FrameworkElement; element != null; element = element.Parent as FrameworkElement)
            {
                chart = element as Chart;
                if (chart != null)
                {
                    break;
                }
            }
            return ((chart != null) && (chart.UpdateCount <= 0));
        }

        internal void ClearAxes()
        {
            foreach (AxisCanvas canvas in this._axes)
            {
                if ((canvas.Axis != this._ax.Axis) && (canvas.Axis != this._ay.Axis))
                {
                    this._view.Axes.Remove(canvas.Axis);
                }
            }
            this._axes.Clear();
            this._axes.Add(this._ax);
            this._axes.Add(this._ay);
        }

        public double ConvertBackX(double x)
        {
            return ((IAxis)this._ax).ToData(x);
        }

        public double ConvertBackY(double y)
        {
            return ((IAxis)this._ay).ToData(y);
        }

        public Point ConvertPoint(Point pt)
        {
            if (this._ast == AxisStyle.Radar)
            {
                double radius = this._radarView.Radius;
                Point center = this._radarView.Center;
                double angle = (6.2831853071795862 * (pt.X - this._ax.Axis.ActualMin)) / (this._ax.Axis.ActualMax - this._ax.Axis.ActualMin);
                angle = this._radarView.GetAngle(angle);
                double num3 = (radius * (pt.Y - this._ay.Axis.ActualMin)) / (this._ay.Axis.ActualMax - this._ay.Axis.ActualMin);
                return new Point(center.X + (num3 * Math.Cos(angle)), center.Y + (num3 * Math.Sin(angle)));
            }
            return new Point(this._ax.ConvertEx(pt.X), this._ay.ConvertEx(pt.Y));
        }

        public Point ConvertPoint(Point pt, Axis ax, Axis ay)
        {
            double radius = this._radarView.Radius;
            Point center = this._radarView.Center;
            double angle = (6.2831853071795862 * (pt.X - ax.ActualMin)) / (ax.ActualMax - ax.ActualMin);
            angle = this._radarView.GetAngle(angle);
            if ((pt.Y > ay.ActualMax) || (pt.Y < ay.ActualMin))
            {
                return new Point(double.NaN, double.NaN);
            }
            double num3 = (radius * (pt.Y - ay.ActualMin)) / (ay.ActualMax - ay.ActualMin);
            return new Point(center.X + (num3 * Math.Cos(angle)), center.Y + (num3 * Math.Sin(angle)));
        }

        public double ConvertX(double x)
        {
            return this._ax.ConvertEx(x);
        }

        private double ConvertX(double x, double left, double right)
        {
            if (this._ax.ReversedInternal)
            {
                return (right - (((right - left) * (x - this._ax.Min0)) / (this._ax.Max0 - this._ax.Min0)));
            }
            return (left + (((right - left) * (x - this._ax.Min0)) / (this._ax.Max0 - this._ax.Min0)));
        }

        public double ConvertY(double y)
        {
            return this._ay.ConvertEx(y);
        }

        private double ConvertY(double y, double top, double bottom)
        {
            if (this._ay.ReversedInternal)
            {
                return (top + (((bottom - top) * (y - this._ay.Min0)) / (this._ay.Max0 - this._ay.Min0)));
            }
            return (bottom - (((bottom - top) * (y - this._ay.Min0)) / (this._ay.Max0 - this._ay.Min0)));
        }

        public double ConvertZ(double z)
        {
            throw new NotImplementedException("The method or operation is not implemented.");
        }

        private void CreateDataObjects(IRenderer renders)
        {
            if (this._startDataIdx >= 0)
            {
                int num = this.InternalChildren.Count - this._startDataIdx;
                for (int j = 0; j < num; j++)
                {
                    PlotElement sender = this.InternalChildren[this._startDataIdx] as PlotElement;
                    this.InternalChildren.RemoveAt(this._startDataIdx);
                    if (((sender != null) && (sender.DataPoint != null)) && (sender.DataPoint.Series != null))
                    {
                        sender.DataPoint.Series.FirePlotElementUnloaded(sender, EventArgs.Empty);
                    }
                }
            }
            Shape plotShape = this._view.PlotShape;
            if ((plotShape != null) && !this.InternalChildren.Contains(plotShape))
            {
                this.InternalChildren.Insert(0, plotShape);
            }
            this._startDataIdx = this.InternalChildren.Count;
            IView2DRenderer renderer = renders as IView2DRenderer;
            if (renderer != null)
            {
                renderer.CoordConverter = this;
                UIElement[] elementArray = renderer.Generate();
                BaseRenderer renderer2 = renders as BaseRenderer;
                if (renderer2 != null)
                {
                    renderer2.FireRendered(this, EventArgs.Empty);
                }
                Chart element = null;
                if ((this._view != null) && (this._view.Chart != null))
                {
                    element = this._view.Chart;
                }
                VisualEffect ve = null;
                if ((element != null) && (element.VisualEffect != null))
                {
                    ve = element.VisualEffect;
                }
                if (elementArray == null)
                {
                    while (base.Children.Count > 1)
                    {
                        base.Children.RemoveAt(base.Children.Count - 1);
                    }
                }
                else
                {
                    int length = elementArray.Length;
                    bool flag = (element != null) && !element.IsInVisualTree();
                    if (ve != null)
                    {
                        for (int k = 0; k < length; k++)
                        {
                            DataSeries ds = elementArray[k] as DataSeries;
                            if (ds != null)
                            {
                                this.ProcessElementWithEffects(ve, ds);
                            }
                            this.InternalChildren.Add(elementArray[k]);
                        }
                    }
                    else
                    {
                        for (int m = 0; m < length; m++)
                        {
                            if (elementArray[m] != null)
                            {
                                if (flag)
                                {
                                    elementArray[m].Measure(new Size(10000.0, 10000.0));
                                    elementArray[m].Arrange(new Rect(0.0, 0.0, 10000.0, 10000.0));
                                    Canvas canvas = elementArray[m] as Canvas;
                                    if (canvas != null)
                                    {
                                        foreach (UIElement element2 in canvas.Children)
                                        {
                                            element2.Measure(new Size(10000.0, 10000.0));
                                            element2.Arrange(new Rect(0.0, 0.0, 10000.0, 10000.0));
                                        }
                                    }
                                }
                                if (!this.InternalChildren.Contains(elementArray[m]))
                                {
                                    FrameworkElement element3 = elementArray[m] as FrameworkElement;
                                    if (element3 != null)
                                    {
                                        Panel parent = element3.Parent as Panel;
                                        if (parent != null)
                                        {
                                            parent.Children.Remove(elementArray[m]);
                                        }
                                    }
                                    this.InternalChildren.Add(elementArray[m]);
                                }
                            }
                        }
                    }
                    while (base.Children.Count > 1)
                    {
                        base.Children.RemoveAt(base.Children.Count - 1);
                    }
                }
            }
            int count = this._view.Layers.Count;
            for (int i = 0; i < count; i++)
            {
                FrameworkElement element4 = this._view.Layers[i] as FrameworkElement;
                if (element4 != null)
                {
                    Canvas.SetLeft(element4, this.PlotRect.X);
                    Canvas.SetTop(element4, this.PlotRect.Y);
                    element4.Width = this.PlotRect.Width;
                    element4.Height = this.PlotRect.Height;
                    base.Children.Add(element4);
                }
            }
            foreach (UIElement element5 in this._view.Children)
            {
                if (!base.Children.Contains(element5))
                {
                    base.Children.Add(element5);
                }
            }
        }

        private object[] GetItems(Renderer2D rend, AxisCanvas ax)
        {
            if (rend != null)
            {
                if (rend.Inverted)
                {
                    if (ax == this._ay)
                    {
                        return rend.ItemNames;
                    }
                }
                else if (ax == this._ax)
                {
                    return rend.ItemNames;
                }
            }
            return null;
        }

        private void PerformPlotAreaLayout(Size arrangeSize)
        {
            List<AreaDef> list = new List<AreaDef>();
            List<AreaDef> list2 = new List<AreaDef>();
            int count = this._view.Axes.Count;
            for (int i = 0; i < count; i++)
            {
                Axis item = this._view.Axes[i];
                if (item.AxisType == AxisType.X)
                {
                    while (list.Count <= item.PlotAreaIndex)
                    {
                        list.Add(new AreaDef());
                    }
                    list[item.PlotAreaIndex].Axes.Add(item);
                }
                else if (item.AxisType == AxisType.Y)
                {
                    while (list2.Count <= item.PlotAreaIndex)
                    {
                        list2.Add(new AreaDef());
                    }
                    list2[item.PlotAreaIndex].Axes.Add(item);
                }
            }
            int ncols = list.Count;
            int nrows = list2.Count;
            Renderer2D renderer = this._view.Renderer as Renderer2D;
            Size size = new Size(arrangeSize.Width, 0.3 * arrangeSize.Height);
            Size size2 = new Size(arrangeSize.Height, 0.3 * arrangeSize.Width);
            double left = 0.0;
            double top = 0.0;
            double width = arrangeSize.Width;
            double height = arrangeSize.Height;
            for (int j = 0; j < ncols; j++)
            {
                AreaDef def = list[j];
                def.Right = arrangeSize.Width;
                def.Bottom = arrangeSize.Height;
                for (int num10 = 0; num10 < def.Axes.Count; num10++)
                {
                    AxisCanvas iax = def.Axes[num10].iax as AxisCanvas;
                    Size size3 = iax.GetSize(this.GetItems(renderer, iax), false);
                    if (size3.Height > size.Height)
                    {
                        size3.Height = size.Height;
                    }
                    size3.Width = size.Width;
                    iax.DesiredSize = size3;
                    if (j == 0)
                    {
                        def.Left = Math.Max(def.Left, iax.AnnoSize.Width * 0.5);
                    }
                    if (j == (ncols - 1))
                    {
                        def.Right = Math.Min(def.Right, arrangeSize.Width - (iax.AnnoSize.Width * 0.5));
                    }
                    if (iax.IsNear)
                    {
                        def.Bottom -= size3.Height;
                    }
                    else if (iax.IsFar)
                    {
                        def.Top += size3.Height;
                    }
                }
            }
            for (int k = 0; k < nrows; k++)
            {
                AreaDef def2 = list2[k];
                def2.Right = arrangeSize.Width;
                def2.Bottom = arrangeSize.Height;
                for (int num12 = 0; num12 < def2.Axes.Count; num12++)
                {
                    AxisCanvas ax = def2.Axes[num12].iax as AxisCanvas;
                    Size size4 = ax.GetSize(this.GetItems(renderer, ax), false);
                    if (size4.Height > size2.Height)
                    {
                        size4.Height = size2.Height;
                    }
                    size4.Width = size2.Width;
                    ax.DesiredSize = size4;
                    if (k == 0)
                    {
                        def2.Top = Math.Max(def2.Top, ax.AnnoSize.Width * 0.5);
                    }
                    if (k == (nrows - 1))
                    {
                        def2.Bottom = Math.Min(def2.Bottom, arrangeSize.Height - (ax.AnnoSize.Width * 0.5));
                    }
                    if (ax.IsNear)
                    {
                        def2.Left += size4.Height;
                    }
                    else if (ax.IsFar)
                    {
                        def2.Right -= size4.Height;
                    }
                }
            }
            double num13 = 0.0;
            double num14 = 0.0;
            double num15 = arrangeSize.Width;
            double num16 = arrangeSize.Height;
            for (int m = 0; m < ncols; m++)
            {
                AreaDef def3 = list[m];
                num13 = Math.Max(num13, def3.Left);
                num14 = Math.Max(num14, def3.Top);
                num15 = Math.Min(num15, def3.Right);
                num16 = Math.Min(num16, def3.Bottom);
            }
            for (int n = 0; n < nrows; n++)
            {
                AreaDef def4 = list2[n];
                num13 = Math.Max(num13, def4.Left);
                num14 = Math.Max(num14, def4.Top);
                num15 = Math.Min(num15, def4.Right);
                num16 = Math.Min(num16, def4.Bottom);
            }
            double w = 0.0;
            double h = 0.0;
            this.AdjustMargins(arrangeSize, ref left, ref width, ref top, ref height, ref w, ref h, ref num13, ref num15, ref num14, ref num16);
            this._plot = this._plot0 = new Rect(left, top, w, h);
            double x = left;
            double[] numArray = this._view.PlotAreas.CalculateWidths(w, ncols);
            int num22 = this.InternalChildren.Count - 1;
            for (int num23 = 0; num23 < ncols; num23++)
            {
                num16 = height;
                num14 = top;
                AreaDef def5 = list[num23];
                double num24 = numArray[num23];
                for (int num25 = 0; num25 < def5.Axes.Count; num25++)
                {
                    AxisCanvas canvas3 = def5.Axes[num25].iax as AxisCanvas;
                    canvas3._plot = new Rect(x, this._plot0.Top, num24, this._plot0.Height);
                    Rect r = new Rect();
                    if (canvas3.IsNear)
                    {
                        r = new Rect(x, num16, num24, canvas3.DesiredSize.Height);
                        num16 += canvas3.DesiredSize.Height;
                    }
                    else if (canvas3.IsFar)
                    {
                        r = new Rect(x, num14 - canvas3.DesiredSize.Height, num24, canvas3.DesiredSize.Height);
                        num14 -= canvas3.DesiredSize.Height;
                    }
                    canvas3.Layout(r);
                    if (((canvas3 == this._ax) && (renderer != null)) && !renderer.Inverted)
                    {
                        canvas3.CreateLabels(renderer.ItemNames);
                    }
                    else
                    {
                        canvas3.CreateLabels(null);
                    }
                    canvas3.CreateAnnosAndTicks(false);
                }
                foreach (PlotArea area in this._view.PlotAreas)
                {
                    if (area.Column == num23)
                    {
                        area.SetPlotX(x, num24);
                    }
                }
                x += num24;
            }
            double y = height;
            double[] numArray2 = this._view.PlotAreas.CalculateHeights(h, nrows);
            for (int num27 = 0; num27 < nrows; num27++)
            {
                num13 = left;
                num15 = width;
                AreaDef def6 = list2[num27];
                double num28 = numArray2[num27];
                y -= num28;
                for (int num29 = 0; num29 < def6.Axes.Count; num29++)
                {
                    AxisCanvas canvas4 = def6.Axes[num29].iax as AxisCanvas;
                    canvas4._plot = new Rect(this._plot0.Left, y, this._plot0.Width, num28);
                    Rect rect2 = new Rect();
                    if (canvas4.IsNear)
                    {
                        rect2 = new Rect(num13 - canvas4.DesiredSize.Height, y, num28, canvas4.DesiredSize.Height);
                        num13 -= canvas4.DesiredSize.Height;
                    }
                    else if (canvas4.IsFar)
                    {
                        rect2 = new Rect(num15, y, num28, canvas4.DesiredSize.Height);
                        num15 += canvas4.DesiredSize.Height;
                    }
                    canvas4.Layout(rect2);
                    if (((canvas4 == this._ay) && (renderer != null)) && renderer.Inverted)
                    {
                        canvas4.CreateLabels(renderer.ItemNames);
                    }
                    else
                    {
                        canvas4.CreateLabels(null);
                    }
                    canvas4.CreateAnnosAndTicks(false);
                }
                foreach (PlotArea area2 in this._view.PlotAreas)
                {
                    if (area2.Row == num27)
                    {
                        area2.SetPlotY(y, num28);
                    }
                }
            }
            foreach (PlotArea area3 in this._view.PlotAreas)
            {
                UIElement uIElement = area3.UIElement;
                if ((uIElement != null) && !this.InternalChildren.Contains(uIElement))
                {
                    this.InternalChildren.Insert(num22++, uIElement);
                }
            }
        }

        private void PrepareAxes()
        {
            Renderer2D renderer = this._view.Renderer as Renderer2D;
            int count = this._axes.Count;
            for (int i = 0; i < count; i++)
            {
                Axis axis = this._axes[i];
                if ((axis != this._ax) && (axis != this._ay))
                {
                    Point min = new Point(double.NaN, double.NaN);
                    Point max = new Point(double.NaN, double.NaN);
                    if (renderer != null)
                    {
                        foreach (DataSeries series in renderer.Series)
                        {
                            bool flag = series.AxisX == axis.AxisName;
                            bool flag2 = series.AxisY == axis.AxisName;
                            if (flag || flag2)
                            {
                                series.GetMinMax(ref min, ref max);
                            }
                        }
                        if (renderer.Inverted)
                        {
                            double x = min.X;
                            min.X = min.Y;
                            min.Y = x;
                            x = max.X;
                            max.X = max.Y;
                            max.Y = x;
                        }
                    }
                    switch (axis.AxisType)
                    {
                        case AxisType.X:
                            axis.SetLimitsAux(min.X, max.X);
                            break;

                        case AxisType.Y:
                            axis.SetLimitsAux(min.Y, max.Y);
                            break;
                    }
                }
                axis.RoundLimits();
                if (axis.Axis.IsDependent)
                {
                    double scale = 1.0;
                    double num5 = 0.0;
                    Func<double, double> dependentAxisConverter = axis.Axis.DependentAxisConverter;
                    if (axis.AxisType == AxisType.X)
                    {
                        if (dependentAxisConverter != null)
                        {
                            double num6 = dependentAxisConverter(this._ax.Min0);
                            double num7 = dependentAxisConverter(this._ax.Max0);
                            if (num6 <= num7)
                            {
                                axis.Min0 = axis._min = num6;
                                axis.Max0 = axis._max = num7;
                            }
                            else
                            {
                                axis.Min0 = axis._min = num7;
                                axis.Max0 = axis._max = num6;
                            }
                        }
                        else
                        {
                            axis.Min0 = axis._min = this._ax.Min0;
                            axis.Max0 = axis._max = this._ax.Max0;
                        }
                        num5 = this._ax.Axis.Value;
                        scale = this._ax.Axis.Scale;
                    }
                    else if (axis.AxisType == AxisType.Y)
                    {
                        if (dependentAxisConverter != null)
                        {
                            double num8 = dependentAxisConverter(this._ay.Min0);
                            double num9 = dependentAxisConverter(this._ay.Max0);
                            if (num8 <= num9)
                            {
                                axis.Min0 = axis._min = num8;
                                axis.Max0 = axis._max = num9;
                            }
                            else
                            {
                                axis.Min0 = axis._min = num9;
                                axis.Max0 = axis._max = num8;
                            }
                        }
                        else
                        {
                            axis.Min0 = axis._min = this._ay.Min0;
                            axis.Max0 = axis._max = this._ay.Max0;
                        }
                        num5 = this._ay.Axis.Value;
                        scale = this._ay.Axis.Scale;
                    }
                    if (scale < 1.0)
                    {
                        double num10 = (axis.Max0 - axis.Min0) * scale;
                        axis._min = axis.Min0 + (num5 * ((axis.Max0 - axis.Min0) - num10));
                        axis._max = axis._min + num10;
                    }
                }
                axis.ClearLabelsAndTicks();
            }
        }

        private void ProcessElementWithEffects(VisualEffect ve, DataSeries ds)
        {
            List<UIElement> list = ds.Children.ToList<UIElement>();
            int count = list.Count;
            ds.Children.Clear();
            for (int i = 0; i < count; i++)
            {
                this.ProcessElementWithEffects(ve, list[i], ds.Children);
            }
        }

        private void ProcessElementWithEffects(VisualEffect ve, UIElement element, UIElementCollection coll)
        {
            if (element is PlotElement)
            {
                PlotElement pe = (PlotElement)element;
                PlotElement element2 = pe;
                if (element2 == null)
                {
                    coll.Add(element);
                }
                else
                {
                    EventHandler handler = null;
                    EventHandler handler2 = null;
                    if (pe is Symbol)
                    {
                        pe.Measure(new Size(10000.0, 10000.0));
                    }
                    UIElement back = ve.CreateBackgroundEffect(pe.Shape);
                    if (back != null)
                    {
                        Canvas.SetLeft(back, Canvas.GetLeft(element2));
                        Canvas.SetTop(back, Canvas.GetTop(element2));
                        if (pe is PieSlice)
                        {
                            Canvas.SetZIndex(back, -1);
                        }
                        if (pe.Clip != null)
                        {
                            back.Clip = VfxTools.CloneGeometry(pe.Clip);
                        }
                        if (handler == null)
                        {
                            handler = (s, e) => back.RenderTransform = pe.RenderTransform;
                        }
                        pe.AfterLoaded += handler;
                        coll.Add(back);
                        pe.Effects.Add(back);
                    }
                    coll.Add(element);
                    UIElement front = ve.CreateForegroundEffect(pe.Shape);
                    if (front != null)
                    {
                        Canvas.SetLeft(front, Canvas.GetLeft(element2));
                        Canvas.SetTop(front, Canvas.GetTop(element2));
                        if (handler2 == null)
                        {
                            handler2 = (s, e) => front.RenderTransform = pe.RenderTransform;
                        }
                        pe.AfterLoaded += handler2;
                        coll.Add(front);
                        pe.Effects.Add(front);
                    }
                }
            }
            else
            {
                coll.Add(element);
            }
        }

        private void RebuildTree()
        {
            if (this.CanUpdate())
            {
                if ((this._view.Renderer != null) && this._view.Renderer.Dirty)
                {
                    this._rebuild = true;
                }
                if (this._rebuild && (this._view.Renderer != null))
                {
                    this.CreateDataObjects(this._view.Renderer);
                    this._rebuild = false;
                    this._view.Renderer.Dirty = false;
                }
            }
        }

        internal void RemoveAxis(Axis ax)
        {
            foreach (Axis axis in this._axes)
            {
                if (axis.Axis == ax)
                {
                    this._axes.Remove(axis);
                    this.InternalChildren.Remove(axis);
                    this._startDataIdx--;
                    break;
                }
            }
        }

        internal void Reset()
        {
        }

        internal void SetAxisX(Axis ax)
        {
            int index = this.InternalChildren.IndexOf(this._ax);
            int num2 = this._axes.IndexOf(this._ax);
            this.InternalChildren.Remove(this._ax);
            this._axes.Remove(this._ax);
            this._ax = ax;
            this.InternalChildren.Insert(index, this._ax);
            this._axes.Insert(num2, this._ax);
        }

        internal void SetAxisY(Axis ay)
        {
            int index = this.InternalChildren.IndexOf(this._ay);
            int num2 = this._axes.IndexOf(this._ay);
            this.InternalChildren.Remove(this._ay);
            this._axes.Remove(this._ay);
            this._ay = ay;
            this.InternalChildren.Insert(index, this._ay);
            this._axes.Insert(num2, this._ay);
        }

        internal void UpdateCacheMode()
        {
            if (Environment.Version.Major >= 4)
            {
                try
                {
                    typeof(Canvas).GetProperty("CacheMode").SetValue(this._intCanvas, this._view.CacheMode, null);
                }
                catch
                {
                }
            }
        }

        internal void UpdateLayout(Size arrangeSize)
        {
            this._ax.Axis = this._view.AxisX;
            this._ay.Axis = this._view.AxisY;
            List<string> list = new List<string>();
            foreach (Axis axis in this._axes)
            {
                if ((axis.PositionInternal & AxisPosition.OverData) > AxisPosition.Near)
                {
                    Canvas.SetZIndex(axis, 1);
                }
                else
                {
                    Canvas.SetZIndex(axis, 0);
                }
                ((IAxis)axis).ClearLabels();
                axis.ResetLimits();
                if (this._view != null)
                {
                    axis.Chart = this._view.Chart;
                }
                if (((axis != this._ax) && (axis != this._ay)) && !string.IsNullOrEmpty(axis.AxisName))
                {
                    list.Add(axis.AxisName);
                }
            }
            if (this._view.Renderer != null)
            {
                Rect emptyRect = Extensions.EmptyRect;
                IView2DRenderer renderer = this._view.Renderer as IView2DRenderer;
                if (renderer == null)
                {
                    return;
                }
                this._ast = renderer.Axis;
                Size sz = new Size(base.Width, base.Height);
                Renderer2D rendererd = renderer as Renderer2D;
                if (rendererd != null)
                {
                    rendererd.ValidAuxAxes = list.ToArray();
                    if (this._plot.Width > 0.0)
                    {
                        sz.Width = this._plot.Width;
                    }
                    if (this._plot.Height > 0.0)
                    {
                        sz.Height = this._plot.Height;
                    }
                }
                Rect rect = renderer.Measure(sz);
                if (emptyRect.IsEmptyRect())
                {
                    emptyRect = rect;
                }
                else
                {
                    emptyRect.Union(rect);
                }
                if (emptyRect.Width > 0.0)
                {
                    this._ax.SetLimits(emptyRect.X, emptyRect.X + emptyRect.Width);
                }
                if (emptyRect.Height > 0.0)
                {
                    this._ay.SetLimits(emptyRect.Y, emptyRect.Y + emptyRect.Height);
                }
            }
            switch (this._ast)
            {
                case AxisStyle.None:
                    if ((base.Width > 10.0) && (base.Height > 10.0))
                    {
                        this._plot = new Rect(5.0, 5.0, base.Width - 10.0, base.Height - 10.0);
                    }
                    foreach (AxisCanvas canvas2 in this._axes)
                    {
                        canvas2.Visibility = Utils.VisHidden;
                    }
                    break;

                case AxisStyle.Cartesian:
                    this.UpdateLayoutCartesian(arrangeSize);
                    break;

                case AxisStyle.Radar:
                    foreach (AxisCanvas canvas in this._axes)
                    {
                        canvas.Visibility = Visibility.Collapsed;
                    }
                    this.UpdateLayoutRadar(arrangeSize);
                    break;
            }
            Shape plotShape = this._view.PlotShape;
            if (plotShape != null)
            {
                Canvas.SetLeft(plotShape, this._view.PlotRect.Left);
                Canvas.SetTop(plotShape, this._view.PlotRect.Top);
                plotShape.Width = this._view.PlotRect.Width;
                plotShape.Height = this._view.PlotRect.Height;
                if (this._ast == AxisStyle.None)
                {
                    plotShape.Visibility = Visibility.Collapsed;
                }
                else
                {
                    plotShape.Visibility = Visibility.Visible;
                }
            }
            this._rebuild = true;
            this.RebuildTree();
        }

        private void UpdateLayoutCartesian(Size arrangeSize)
        {
            if ((arrangeSize.Width != 0.0) && (arrangeSize.Height != 0.0))
            {
                int count = this._axes.Count;
                this.PrepareAxes();
                bool hasPlotAreas = this._view.HasPlotAreas;
                PlotArea area = this._view.UpdateMainPlotArea(hasPlotAreas);
                if (hasPlotAreas)
                {
                    this.PerformPlotAreaLayout(arrangeSize);
                }
                else
                {
                    Renderer2D renderer = this._view.Renderer as Renderer2D;
                    Size size = new Size(arrangeSize.Width, 0.3 * arrangeSize.Height);
                    Size size2 = new Size(arrangeSize.Height, 0.3 * arrangeSize.Width);
                    double num2 = 0.0;
                    double num3 = 0.0;
                    double width = arrangeSize.Width;
                    double height = arrangeSize.Height;
                    double left = 0.0;
                    double top = 0.0;
                    double right = arrangeSize.Width;
                    double bottom = arrangeSize.Height;
                    for (int i = 0; i < count; i++)
                    {
                        Axis ax = this._axes[i];
                        double origin = ax.Axis.Origin;
                        if (ax.AxisType == AxisType.X)
                        {
                            Size size3 = ax.GetSize(this.GetItems(renderer, ax), false);
                            if (size3.Height > size.Height)
                            {
                                size3.Height = size.Height;
                            }
                            size3.Width = size.Width;
                            ax.DesiredSize = size3;
                            bool flag2 = (!double.IsNaN(origin) && (origin <= this._ay.Max0)) && (origin >= this._ay.Min0);
                            if (ax.IsNear)
                            {
                                num2 = Math.Max(num2, ax.AnnoSize.Width * 0.5);
                                width = Math.Min(width, arrangeSize.Width - (ax.AnnoSize.Width * 0.5));
                                if (flag2)
                                {
                                    double num12 = this.ConvertY(origin, top, bottom);
                                    bottom -= Math.Max((double)0.0, (double)((num12 + size3.Height) - bottom));
                                }
                                else
                                {
                                    bottom -= size3.Height;
                                }
                            }
                            else if (ax.IsFar)
                            {
                                num2 = Math.Max(num2, ax.AnnoSize.Width * 0.5);
                                width = Math.Min(width, arrangeSize.Width - (ax.AnnoSize.Width * 0.5));
                                if (flag2)
                                {
                                    double num13 = this.ConvertY(origin, top, bottom);
                                    top += Math.Max((double)0.0, (double)(top - (num13 - size3.Height)));
                                }
                                else
                                {
                                    top += size3.Height;
                                }
                            }
                        }
                        else if (ax.AxisType == AxisType.Y)
                        {
                            Size size4 = ax.GetSize(this.GetItems(renderer, ax), false);
                            if (size4.Height > size2.Height)
                            {
                                size4.Height = size2.Height;
                            }
                            size4.Width = size2.Width;
                            ax.DesiredSize = size4;
                            bool flag3 = (!double.IsNaN(origin) && (origin <= this._ax.Max0)) && (origin >= this._ax.Min0);
                            if (ax.IsNear)
                            {
                                num3 = Math.Max(num3, ax.AnnoSize.Width * 0.5);
                                height = Math.Min(height, arrangeSize.Height - (ax.AnnoSize.Width * 0.5));
                                if (flag3)
                                {
                                    double num14 = this.ConvertX(origin, left, right);
                                    left += Math.Max((double)0.0, (double)(left - (num14 - size4.Height)));
                                }
                                else
                                {
                                    left += size4.Height;
                                }
                            }
                            else if (ax.IsFar)
                            {
                                num3 = Math.Max(num3, ax.AnnoSize.Width * 0.5);
                                height = Math.Min(height, arrangeSize.Height - (ax.AnnoSize.Width * 0.5));
                                if (flag3)
                                {
                                    double num15 = this.ConvertX(origin, left, right);
                                    right -= Math.Max((double)0.0, (double)((num15 + size4.Height) - right));
                                }
                                else
                                {
                                    right -= size4.Height;
                                }
                            }
                        }
                    }
                    double w = 0.0;
                    double h = 0.0;
                    this.AdjustMargins(arrangeSize, ref num2, ref width, ref num3, ref height, ref w, ref h, ref left, ref right, ref top, ref bottom);
                    this._plot = this._plot0 = new Rect(num2, num3, w, h);
                    if (area != null)
                    {
                        area.SetPlotX(this._plot.X, this._plot.Width);
                        area.SetPlotY(this._plot.Y, this._plot.Height);
                        UIElement uIElement = area.UIElement;
                        if ((uIElement != null) && !this.InternalChildren.Contains(uIElement))
                        {
                            this.InternalChildren.Insert(0, uIElement);
                        }
                    }
                    for (int j = 0; j < count; j++)
                    {
                        Axis axis2 = this._axes[j];
                        axis2._plot = this._plot0;
                        double d = axis2.Axis.Origin;
                        if (axis2.AxisType == AxisType.X)
                        {
                            Rect r = new Rect();
                            if ((double.IsNaN(d) || (d > this._ay.Max0)) || (d < this._ay.Min0))
                            {
                                if (axis2.IsNear)
                                {
                                    r = new Rect(num2, bottom, w, axis2.DesiredSize.Height);
                                    bottom += axis2.DesiredSize.Height;
                                }
                                else if (axis2.IsFar)
                                {
                                    r = new Rect(num2, top - axis2.DesiredSize.Height, w, axis2.DesiredSize.Height);
                                    top -= axis2.DesiredSize.Height;
                                }
                            }
                            else
                            {
                                double y = this.ConvertY(d, this._plot.Top, this._plot.Bottom);
                                if (axis2.IsNear)
                                {
                                    r = new Rect(num2, y, w, axis2.DesiredSize.Height);
                                    bottom += Math.Max((double)0.0, (double)(r.Bottom - this._plot.Bottom));
                                }
                                else if (axis2.IsFar)
                                {
                                    r = new Rect(num2, y - axis2.DesiredSize.Height, w, axis2.DesiredSize.Height);
                                    top -= Math.Max((double)0.0, (double)(this._plot.Top - r.Top));
                                }
                            }
                            axis2.Layout(r);
                        }
                        else if (axis2.AxisType == AxisType.Y)
                        {
                            Rect rect2 = new Rect();
                            if ((double.IsNaN(d) || (d > this._ax.Max0)) || (d < this._ax.Min0))
                            {
                                if (axis2.IsNear)
                                {
                                    rect2 = new Rect(left - axis2.DesiredSize.Height, num3, h, axis2.DesiredSize.Height);
                                    left -= axis2.DesiredSize.Height;
                                }
                                else if (axis2.IsFar)
                                {
                                    rect2 = new Rect(right, num3, h, axis2.DesiredSize.Height);
                                    right += axis2.DesiredSize.Height;
                                }
                            }
                            else
                            {
                                double x = this.ConvertX(d, this._plot.Left, this._plot.Right);
                                if (axis2.IsNear)
                                {
                                    rect2 = new Rect(x - axis2.DesiredSize.Height, num3, h, axis2.DesiredSize.Height);
                                    left -= axis2.DesiredSize.Height;
                                }
                                else if (axis2.IsFar)
                                {
                                    rect2 = new Rect(x, num3, h, axis2.DesiredSize.Height);
                                    right += axis2.DesiredSize.Height;
                                }
                            }
                            axis2.Layout(rect2);
                        }
                        if (((axis2 == this._ax) && (renderer != null)) && !renderer.Inverted)
                        {
                            axis2.CreateLabels(renderer.ItemNames);
                        }
                        else if (((axis2 == this._ay) && (renderer != null)) && renderer.Inverted)
                        {
                            axis2.CreateLabels(renderer.ItemNames);
                        }
                        else
                        {
                            axis2.CreateLabels(null);
                        }
                        axis2.CreateAnnosAndTicks(false);
                    }
                }
            }
        }

        private void UpdateLayoutRadar(Size arrangeSize)
        {
            RadarRenderer renderer = this._view.Renderer as RadarRenderer;
            List<int> list = new List<int>();
            foreach (Axis axis in this._axes)
            {
                if (((axis != this._ax) && (axis != this._ay)) && ((axis.AxisType == AxisType.Y) && (axis.Axis.RadarPointIndices != null)))
                {
                    double naN = double.NaN;
                    double ymax = double.NaN;
                    foreach (int num3 in axis.Axis.RadarPointIndices)
                    {
                        if (!list.Contains(num3))
                        {
                            list.Add(num3);
                        }
                        renderer.GetMinMaxY(num3, ref naN, ref ymax);
                    }
                    if (double.IsNaN(axis._min))
                    {
                        axis.Min0 = axis._min = naN;
                    }
                    if (double.IsNaN(axis._max))
                    {
                        axis.Max0 = axis._max = ymax;
                    }
                    axis.RoundLimits();
                }
            }
            if (list.Count > 0)
            {
                double ymin = double.NaN;
                double num5 = double.NaN;
                int npts = ((BaseRenderer)this._view.Renderer)._dataInfo.npts;
                for (int i = 0; i < npts; i++)
                {
                    if (!list.Contains(i))
                    {
                        renderer.GetMinMaxY(i, ref ymin, ref num5);
                    }
                }
                if (double.IsNaN(this._ay.Axis.Min))
                {
                    this._ay.Min0 = this._ay._min = ymin;
                }
                if (double.IsNaN(this._ay.Axis.Max))
                {
                    this._ay.Max0 = this._ay._max = num5;
                }
                this._ay.RoundLimits();
            }
            Canvas.SetLeft(this._ay, 0.0);
            Canvas.SetTop(this._ay, 0.0);
            Canvas.SetLeft(this._ax, 0.0);
            Canvas.SetTop(this._ax, 0.0);
            foreach (Axis axis2 in this._axes)
            {
                axis2.Children.Clear();
            }
            Size size = this._ay.GetSize(null, false);
            this._ax.GetSize(renderer.ItemNames, true);
            double width = base.Width;
            double height = base.Height;
            if (double.IsNaN(width))
            {
                width = arrangeSize.Width;
            }
            if (double.IsNaN(height))
            {
                height = arrangeSize.Height;
            }
            Size annoSize = this._ax.AnnoSize;
            this._plot = new Rect(1.1 * annoSize.Width, 1.1 * annoSize.Height, Math.Max((double)8.0, (double)(width - (2.2 * annoSize.Width))), Math.Max((double)8.0, (double)(height - (2.2 * annoSize.Height))));
            Chart chart = this._view.Chart;
            if (chart != null)
            {
                this._radarView.Angle = PolarRadarOptions.GetStartingAngle(chart);
                this._radarView.Direction = PolarRadarOptions.GetDirection(chart);
            }
            this._radarView.IsPolar = renderer.IsPolar;
            this._radarView.Init(this._plot);
            this._ay.Layout(this._radarView.GetAxisYRect(size.Height));
            this._ay.CreateLabels(null);
            this._ay.CreateAnnosAndTicks(true);
            this._ay.Visibility = Visibility.Collapsed;
            foreach (Axis axis3 in this._axes)
            {
                if ((axis3 != this._ay) && (axis3.AxisType == AxisType.Y))
                {
                    axis3.Layout(this._radarView.GetAxisYRect(size.Height));
                    axis3.CreateLabels(null);
                    axis3.CreateAnnosAndTicks(true);
                    axis3.Visibility = Visibility.Collapsed;
                }
            }
            this._ax.Visibility = Visibility.Visible;
            this._ax.CreateLabels(renderer.ItemNames, renderer.IsPolar ? ((double)0x2d) : ((double)0));
            this._ax.CreateAnnosAndTicksRadar(this._radarView, this._ay);
            this._plot0 = this._plot = new Rect(0.1 * annoSize.Width, 0.1 * annoSize.Height, Math.Max((double)8.0, (double)(width - (0.2 * annoSize.Width))), Math.Max((double)8.0, (double)(height - (0.2 * annoSize.Height))));
        }

        // Properties
        internal AxisCanvasCollection Axes
        {
            get
            {
                return this._axes;
            }
        }

        public Rect DataBounds
        {
            get
            {
                return new Rect(this._ax._min, this._ay._min, this._ax._max - this._ax._min, this._ay._max - this._ay._min);
            }
        }

        public Rect DataBounds2D
        {
            get
            {
                return new Rect(this._ax._min, this._ay._min, this._ax._max - this._ax._min, this._ay._max - this._ay._min);
            }
        }

        internal UIElementCollection InternalChildren
        {
            get
            {
                return this._intCanvas.Children;
            }
        }

        internal Rect PlotRect
        {
            get
            {
                return this._plot;
            }
        }

        public Rect ViewBounds
        {
            get
            {
                return new Rect(this._plot.X, this._plot.Y, this._plot.Width, this._plot.Height);
            }
        }

        // Nested Types
        private class AreaDef
        {
            // Fields
            private List<Axis> _axes = new List<Axis>();
            public double Bottom;
            public double Left;
            public double Right;
            public double Top;

            // Properties
            public List<Axis> Axes
            {
                get
                {
                    return this._axes;
                }
            }
        }
    }
}
